<?php

declare(strict_types=1);

namespace App\Controller\Mini\V2\Payment;

use App\Constants\Order\OrderCode;
use App\Constants\Payment\PaymentCode;
use App\Controller\Mini\V2\Controllers;
use App\Exception\InternalException;
use App\Factory\Payment\Factory;
use App\Model\Orders\Order;
use App\Model\Users\Payer;
use App\Services\Orders\Order as OrderServices;
use Hyperf\Collection\Arr;
use Psr\Http\Message\ResponseInterface;
use App\Request\Payment\Payment as PaymentRequest;
use App\Services\Payment\Payment as PaymentServices;
use App\Services\Users\Payer as PayerServices;
use function Hyperf\Translation\__;

class Payment extends Controllers
{
    /**
     * 请求类
     * @var string
     */
    protected string $requestClass = PaymentRequest::class;

    public function __construct(
        PaymentServices $paymentServices,
        protected OrderServices $orderServices,
        protected PayerServices $payerServices
    )
    {
        parent::__construct();
        $this->services = $paymentServices;
    }

    /**
     * 支付下单
     * @param Factory $factory
     * @return ResponseInterface
     * @throws \Throwable
     */
    public function save():ResponseInterface
    {
        $input = $this->input(['no', 'payer_id']);

        /** @var Order $orderModel */
        $orderModel = $this->orderServices->search($input)->firstOrFail();
        if ($orderModel->status == OrderCode::STATUS_CLOSE) {
            return failed(__('message.order.close'));
        }
        if (!in_array($orderModel->pay_status, [OrderCode::PAY_STATUS_PENDING_PAID, OrderCode::PAY_STATUS_PART_PAID])) {
            return failed(__('message.order.status.failed'));
        }

        /** @var Payer $payerModel */
        $payerModel = $this->payerServices->findOrFail($input['payer_id']);

        // 如果订单没有绑定认证信息则去绑定认证信息
        if (!$orderModel->payer ||
            $payerModel->id_card !== $orderModel->payer_no ||
            $payerModel->mobile !== $orderModel->payer_mobile) {

            $this->orderServices->checkCustoms486($payerModel->id_card, $payerModel->mobile, $orderModel->address);
            
            $orderModel->fill([
                'payer_name' => $payerModel->name,
                'payer_no' => $payerModel->id_card,
                'payer_mobile' => $payerModel->mobile,
                'payer' => $payerModel
            ])->save();
        }

        /** @var \App\Model\Payment\Payment $model */
        if ($orderModel->paid_no && $model = $this->services
                ->where('no', $orderModel->paid_no)
                ->where('type', PaymentCode::TYPE_PAYMENT)
                ->first()) {
            if ($model->notify_body && $model->process_at) {
                return failed(__('message.order.paid'));
            }
            if (str_contains($model->code, 'safepay') && $model->created_at->gt(date('Y-m-d H:i:s', time()-60))) {
                if (!isset($model->response_body['code']) ||
                    $model->response_body['code'] !== '0' ||
                    !isset($model->response_body['data']) ||
                    !isset($model->response_body['data']['code']) ||
                    $model->response_body['data']['code'] != '00') {
                    throw new InternalException($model->response_body['message']);
                }
                return success($model->response_body['data']['resultContent']);
            }
            switch ($model->code) {
                case 'sandpayMini':
                    return success(json_encode(Arr::get(Arr::get($model->response_body, 'bizData'), 'credential'), JSON_UNESCAPED_UNICODE));
                case 'wechatMini':

                    break;
            }
        }

        [, , $responseParams] = $orderModel->goPay($input);

        if (is_array($responseParams)) {
            $responseParams = json_encode($responseParams, JSON_UNESCAPED_UNICODE);
        }
        logs($responseParams);

        return success($responseParams);
    }
}
